package com.hyperfix.user.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.core.lang.UUID;
import com.hyperfix.common.auth.RequiresRole;
import com.hyperfix.common.holder.UserHolder;
import com.hyperfix.models.common.R;
import com.hyperfix.models.user.dtos.UserDTO;
import com.hyperfix.models.user.vos.CaptchaVO;
import com.hyperfix.models.user.vos.LoginVO;
import com.hyperfix.models.user.vos.PasswordFindVO;
import com.hyperfix.models.user.vos.PasswordUpdateVO;
import com.hyperfix.user.service.UserService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import static com.hyperfix.models.constant.common.LoginConstant.*;

/**
 * @author JiangChunYu
 * 2024/4/5
 */
@Validated
@RestController
@RequestMapping("/login")
public class UserController {
    @Resource
    private UserService userService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 登录
     *
     * @param loginVO 登录 vo
     * @return {@link R}<{@link UserDTO}> 必要的用户数据
     */
    @PostMapping("/login_auth")
    public R<UserDTO> login(@RequestBody @Validated LoginVO loginVO) {
        return userService.login(loginVO);
    }

    /**
     * 生成验证码
     *
     * @param response 响应
     * @throws IOException io异常
     */
    @PostMapping("/captcha")
    public void generateCaptcha(@RequestBody CaptchaVO captchaVO, HttpServletResponse response) throws IOException {
        CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(captchaVO.getWidth(), captchaVO.getHeight(), 4, 20);
        String uuid = UUID.fastUUID().toString();
        stringRedisTemplate.opsForValue().set(CAPTCHA_KEY_PREFIX + uuid, captcha.getCode(), CAPTCHA_TTL_Seconds, TimeUnit.SECONDS);
        captcha.write(response.getOutputStream());
        response.setHeader("captchaToken", uuid);
        response.setHeader("Access-Control-Expose-Headers", "captchaToken");
    }

    /**
     * 注销
     *
     * @return {@link R}<{@link String}> 是否注销成功
     */
    @PostMapping("/logout")
    public R<String> logout(HttpServletRequest request) {
        String token = request.getHeader("token");
        UserDTO userDTO = UserHolder.getUser();
        String username = userDTO.getUsername();
        boolean success = userService.clearUserContext(token, username);
        if (!success) {
            return R.error("退出登录失败");
        }
        return R.success("退出登录成功");
    }

    /**
     * 切换用户状态(启用 禁用)
     *
     * @param username 用户名
     * @return {@link R}<{@link String}> 是否切换用户状态成功
     */
    @RequiresRole("admin")
    @GetMapping("/disable/{username}")
    public R<String> disable(@PathVariable("username") @NotBlank(message = "用户名不能为空") String username) {
        return userService.disable(username);
    }

    /**
     * 更改密码
     *
     * @param passwordUpdateVO 修改密码的表单(用户名，旧密码，新密码)
     * @return {@link R}<{@link String}> 是否修改成功
     */
    @PostMapping("/changePassword")
    public R<String> changePassword(@RequestBody @Validated PasswordUpdateVO passwordUpdateVO, HttpServletRequest request) {
        String token = request.getHeader("token");
        return userService.changePassword(passwordUpdateVO, token);
    }

    /**
     * 找回密码 TODO 2025.3.13 有问题 应该先向邮箱发一个验证码
     *
     * @param passwordFindVO 密码查找 VO
     * @return {@link R}<{@link String}> 是否找回成功
     */
    @PostMapping("/findPassword")
    public R<String> findPassword(@RequestBody @Validated PasswordFindVO passwordFindVO) {
        return userService.findPassword(passwordFindVO);
    }
}
